package ru.spb.osll.myfit.server.execute;

import org.apache.log4j.Logger;
import ru.spb.osll.myfit.common.ExecutingResult;
import ru.spb.osll.myfit.common.PageExecutingResult;
import ru.spb.osll.myfit.common.TestResultMetadataConstants;
import ru.spb.osll.myfit.util.FileHelper;
import ru.spb.osll.myfit.util.StringUtils;

import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

public class PageExecutor extends Thread {

	private final PageExecutingResult m_pageResult;
	private String m_id;
	private final String m_pagePath;
	private FitNesseTestRunner m_runner;
	private FixtureListenerImpl m_fixtureListener;
	private PageWriter m_pageWriter;
	private FileHelper m_helper;
	private Date m_time;
	private String m_depsPath;
	private String m_fixturePath;
	private boolean m_deleteDeps;
	private Map<String, String> m_metadata = new TreeMap<String, String>();
	private String m_metadataFilePath = null;
	private Logger m_log = Logger.getLogger(getClass());

	public PageExecutor(FitNesseTestRunner runner, String pagePath,
                       FixtureListenerImpl listener, PageWriter pageWriter, FileHelper fileHelper, Date time, String id,
                       String depsPath, String fixturePath, boolean deleteDeps) {
    m_id = id;
    m_pagePath = pagePath;
    m_pageResult = new PageExecutingResult(m_id);
    m_runner = runner;
    m_fixtureListener = listener;
    m_pageWriter = pageWriter;
    m_helper = fileHelper;
    m_time = time;
    m_depsPath = depsPath;
    m_fixturePath = fixturePath;
    m_deleteDeps = deleteDeps;
  }

	@Override
	public void run() {
		try {
      Date startTime = new Date();
      m_metadata.put(TestResultMetadataConstants.START_TIME, new SimpleDateFormat(TestResultMetadataConstants.METADATA_DATE_FORMAT, Locale.ENGLISH).format(startTime));

      synchronized (m_pageResult) {
				m_pageResult.setState(ExecutingResult.ExecutingState.PROGRESS);
			}
			String actualPagePath = (m_pagePath != null) ? m_pagePath
					: "FrontPage";
			m_log.info("Executing test " + actualPagePath);
			
			m_runner.run(actualPagePath);

			synchronized (m_pageResult) {
				m_pageResult.setState(ExecutingResult.ExecutingState.FINISH);
			}

			if (m_pageWriter != null) {
			  m_pageWriter.writeStream(m_fixtureListener.getOutputStream(),
                      m_pageResult.getCounts());
			}
			
			Date endTime = new Date();
			m_metadata.put(TestResultMetadataConstants.END_TIME, new SimpleDateFormat(TestResultMetadataConstants.METADATA_DATE_FORMAT, Locale.ENGLISH).format(endTime));
			long duration = endTime.getTime() - startTime.getTime();
      m_metadata.put(TestResultMetadataConstants.DURATION, StringUtils.dateDiffToString(duration));
   			
		  TestResultMetadataDao dao = new TestResultMetadataDao();
	    OutputStream stream = null;
	    try {
	      stream = m_helper.openFile(m_metadataFilePath);
	      dao.save(m_metadata, stream);
	    } catch(IOException e) {
	    } finally {
	      m_helper.close(stream);
	    }
		} catch (Exception e) {
			synchronized (m_pageResult) {
				m_pageResult.setState(ExecutingResult.ExecutingState.FAIL);
			}
		}
		
		if(m_deleteDeps) {
		  m_log.info("deleting " + m_depsPath + " and " + m_fixturePath);
		  m_helper.delete(m_depsPath);
		  m_helper.delete(m_fixturePath);
		}
	}

	public String getTestId() {
		return m_id;
	}
	
	public PageExecutingResult getPageExecutingResult() {
    synchronized (m_pageResult) {
      m_pageResult.removeAllTables();
      m_pageResult.addAllExecutedTable(m_fixtureListener.getTables());
      m_pageResult.setCounts(m_fixtureListener.getCounts());
      PageExecutingResult result = new PageExecutingResult(m_pageResult);
      result.setName(m_pagePath);
      result.setStartTime(m_time);
      result.setMetadata(m_metadata);
      return result;
    }
  }
  
  public void setMetadata(Map<String, String> metadata, String metadataFilePath) {
    m_metadata = metadata;
    m_metadataFilePath = metadataFilePath;
  }
} 

